#include <libdswlivevideo/dswlivevideo.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <lcd200_v3/lcd_fb.h>
#include <frammap/frammap_if.h>
#include "nosignal.h"

#define LINE_WIDTH 1
#define OSD_ZK "/share/font/HZK16S.dat"
#define TXT_OSD_OFFSET_X 10
#define TXT_OSD_OFFSET_Y 10
#define TM_OSD_OFFSET_X TXT_OSD_OFFSET_X
#define TM_OSD_OFFSET_Y (-(20 + 16))
#define RGB24_2_565(r, g, b) (((r << 8) & 0xf800) | ((g << 3) & 0x07e0) | (b >> 3))
#define FRAME_MAP_DEV "/dev/frammap0"

#define F_WIDTH 1920
#define F_HEIGHT 1080

CDswlivevideo* g_pLiveVideo;

CDswlivevideo::CDswlivevideo(LPST_ENV_T pEnv)
: CDswbase(pEnv)
, m_nThreadID(INVALID_PTHREAD_ID)
, m_pClrwinBuf(NULL)
{
	LOG4CPLUS_DEBUG(log_dsw, "Create Live video!");
	g_pLiveVideo = this;
	memset(&m_nScreenInfo, 0, sizeof(m_nScreenInfo));
	InitLiveView(&m_nScreenInfo, m_nLocalScreen, m_nRemoteScreen);
}

CDswlivevideo::~CDswlivevideo()
{
	UnInitLiveView(&m_nScreenInfo);
	LOG4CPLUS_DEBUG(log_dsw, "Destroy Live video!");
}

void CDswlivevideo::UnInitSignal(LPST_SIGNAL_T pSignal)
{
	pthread_mutex_destroy(&pSignal->nLock);
}

void CDswlivevideo::InitSignal(LPST_SIGNAL_T pSignal)
{
	pthread_mutex_init(&pSignal->nLock, NULL);
	pSignal->nMask = MASK_SIGNAL_LOCAL_0 | MASK_SIGNAL_LOCAL_1 | MASK_SIGNAL_LOCAL_2 | MASK_SIGNAL_LOCAL_3 |
		MASK_SIGNAL_REMOTE_0 | MASK_SIGNAL_REMOTE_1 | MASK_SIGNAL_REMOTE_2 | MASK_SIGNAL_REMOTE_3;
	int i;
	for (i = 0; i < MAX_CHANNEL_LOCAL; i++)
		pSignal->nSignal_local[i] = VIDEO_UNKNOW_SIGNAL;
	for (i = 0; i < MAX_CHANNEL_REMOTE; i++)
		pSignal->nSignal_remote[i] = VIDEO_UNKNOW_SIGNAL;
	ST_DEVICE_BASE_T nBaseParam;
	SendMessage(PMSG_GET_DEVICE_BASE_PARAM, &nBaseParam);
	if ((nBaseParam.type == DEV_MIXDVR_DVR) || (nBaseParam.type == DEV_MIXDVR_MIX) ||
		(nBaseParam.type == DEV_MIXDVR_DVR_G) || (nBaseParam.type == DEV_MIXDVR_MIX_G)){
		FILE* fp = fopen("/proc/nvp1914c.0/status", "r");
		if (fp == NULL){
			LOG4CPLUS_ERROR(log_dsw, "Open /proc/nvp1914c.0/status failed! err = " << strerror(errno));
			return;
		}
		char line[512];
		while(fgets(line, sizeof(line), fp)){
			char* pPos = strstr(line, "Video_");
			int nIn, nCh;
			char sStatus[32];
			if (!pPos)
				continue;
			if (sscanf(line, " %d %d %[^\n]", &nIn, &nCh, sStatus) != 3)
				continue;
			if (strcmp("Video_On", sStatus) == 0)
				pSignal->nSignal_local[nCh] = VIDEO_PRESENT;
			else
				pSignal->nSignal_local[nCh] = VIDEO_NO_SIGNAL;
		}
		fclose(fp);
		if ((nBaseParam.type == DEV_MIXDVR_MIX) || (nBaseParam.type == DEV_MIXDVR_MIX_G)){
			for (i = 0; i < MAX_CHANNEL_REMOTE; i++)
				pSignal->nSignal_remote[i] = VIDEO_NO_SIGNAL;
		}
	}
	else if ((nBaseParam.type == DEV_MIXDVR_NVR) || (nBaseParam.type == DEV_MIXDVR_NVR_G)){
		for (i = 0; i < MAX_CHANNEL_REMOTE; i++)
			pSignal->nSignal_remote[i] = VIDEO_NO_SIGNAL;
	}
}

void CDswlivevideo::InitLiveView(LPST_SCREEN_INFO_T pScreenInfo, gm_rect_t *pLocalScreen, gm_rect_t *pRemoteScreen)
{
	pScreenInfo->bValid = false;
	memset(&pScreenInfo->gfx_device, 0x00, sizeof(FT2D_GfxDevice));
	pScreenInfo->gfx_funcs = (FT2D_GraphicsDeviceFuncs*)&pScreenInfo->gfx_device.funcs;
	if (driver_init_device(&pScreenInfo->gfx_device , pScreenInfo->gfx_funcs , FT2D_RGB_5650)< 0){
		LOG4CPLUS_ERROR(log_dsw, "Init think2d failed!");
		return;
	}
	pScreenInfo->drv_data = (FT2D_GfxDrv_Data*)&pScreenInfo->gfx_device.drv_data;
	pScreenInfo->tar_data = (FT2D_Surface_Data*)&pScreenInfo->drv_data->target_sur_data;
	pScreenInfo->accel_data = (FT2D_GFX_Setting_Data*)&pScreenInfo->gfx_device.accel_setting_data;

	memcpy(pScreenInfo->tar_data , &pScreenInfo->drv_data->fb_data ,sizeof(FT2D_Surface_Data));

	pScreenInfo->gfx_device.accel_do = FT2D_FILLINGRECT;
	pScreenInfo->gfx_device.accel_param = (FT2D_SettingFlags_T)(FT2D_COLOR_SET | FT2D_DSTINATION_SET);
	pScreenInfo->accel_data->color = COLOUR8888(0, 0, 0, 0);
	if(!pScreenInfo->gfx_funcs->CheckState(&pScreenInfo->gfx_device) && !pScreenInfo->gfx_funcs->SetState(&pScreenInfo->gfx_device)){
		FT2DRectangle rect;
		rect.x = 0;
		rect.y = 0;
		rect.w = pScreenInfo->drv_data->target_sur_data.width;
		rect.h = pScreenInfo->drv_data->target_sur_data.height;
		pScreenInfo->gfx_funcs->FillRectangle(&pScreenInfo->gfx_device , &rect);
		pScreenInfo->gfx_funcs->EmitCommands(&pScreenInfo->gfx_device);
	}
	
	pScreenInfo->nScreen.width = pScreenInfo->gfx_device.drv_data.fb_data.width;
	pScreenInfo->nScreen.height = pScreenInfo->gfx_device.drv_data.fb_data.height;

	ST_VIDEO_PARAM nVParam;
	SendMessage(PMSG_GET_VIDEO_PARAM, &nVParam);
	MakeOsdFont(pScreenInfo, &nVParam);

	InitSignal(&pScreenInfo->nSignal);

	switch(m_pEnv->nDevType){
	case DEV_MIXDVR_DVR:
	case DEV_MIXDVR_DVR_G:
		{
			int nWidth, nHeight;
			FT2DRectangle rect;
			nWidth = pScreenInfo->nScreen.width / 2;
			nHeight = pScreenInfo->nScreen.height / 2;
			rect.x = pLocalScreen[0].x = 0;
			rect.y = pLocalScreen[0].y = 0;
			rect.w = pLocalScreen[0].width = nWidth;
			rect.h = pLocalScreen[0].height = nHeight;
			DrawRect(pScreenInfo, &rect);
			rect.x = pLocalScreen[1].x = nWidth;
			rect.y = pLocalScreen[1].y = 0;
			rect.w = pLocalScreen[1].width = nWidth;
			rect.h = pLocalScreen[1].height = nHeight;
			DrawRect(pScreenInfo, &rect);
			rect.x = pLocalScreen[2].x = 0;
			rect.y = pLocalScreen[2].y = nHeight;
			rect.w = pLocalScreen[2].width = nWidth;
			rect.h = pLocalScreen[2].height = nHeight;
			DrawRect(pScreenInfo, &rect);
			rect.x = pLocalScreen[3].x = nWidth;
			rect.y = pLocalScreen[3].y = nHeight;
			rect.w = pLocalScreen[3].width = nWidth;
			rect.h = pLocalScreen[3].height = nHeight;
			DrawRect(pScreenInfo, &rect);
			pScreenInfo->nLocalScreen[0] = pLocalScreen++;
			pScreenInfo->nLocalScreen[1] = pLocalScreen++;
			pScreenInfo->nLocalScreen[2] = pLocalScreen++;
			pScreenInfo->nLocalScreen[3] = pLocalScreen++;
			memset(pScreenInfo->nRemoteScreen, 0, sizeof(pScreenInfo->nRemoteScreen));
			DrawTxtOsd(pScreenInfo);
			DrawTmOsd(pScreenInfo, time(NULL));
			CREATE_EV(pScreenInfo->nOsdTask, 1, 0, m_pEnv->pEvBase, CDswlivevideo::cbOsdTask, pScreenInfo);
		}
		break;
	case DEV_MIXDVR_NVR:
	case DEV_MIXDVR_NVR_G:
		{
			int nWidth, nHeight;
			FT2DRectangle rect;
			nWidth = pScreenInfo->nScreen.width / 2;
			nHeight = pScreenInfo->nScreen.height / 2;
			rect.x = pRemoteScreen[0].x = 0;
			rect.y = pRemoteScreen[0].y = 0;
			rect.w = pRemoteScreen[0].width = nWidth;
			rect.h = pRemoteScreen[0].height = nHeight;
			DrawRect(pScreenInfo, &rect);
			rect.x = pRemoteScreen[1].x = nWidth;
			rect.y = pRemoteScreen[1].y = 0;
			rect.w = pRemoteScreen[1].width = nWidth;
			rect.h = pRemoteScreen[1].height = nHeight;
			DrawRect(pScreenInfo, &rect);
			rect.x = pRemoteScreen[2].x = 0;
			rect.y = pRemoteScreen[2].y = nHeight;
			rect.w = pRemoteScreen[2].width = nWidth;
			rect.h = pRemoteScreen[2].height = nHeight;
			DrawRect(pScreenInfo, &rect);
			rect.x = pRemoteScreen[3].x = nWidth;
			rect.y = pRemoteScreen[3].y = nHeight;
			rect.w = pRemoteScreen[3].width = nWidth;
			rect.h = pRemoteScreen[3].height = nHeight;
			DrawRect(pScreenInfo, &rect);
			pScreenInfo->nRemoteScreen[0] = pRemoteScreen++;
			pScreenInfo->nRemoteScreen[1] = pRemoteScreen++;
			pScreenInfo->nRemoteScreen[2] = pRemoteScreen++;
			pScreenInfo->nRemoteScreen[3] = pRemoteScreen++;
			memset(pScreenInfo->nLocalScreen, 0, sizeof(pScreenInfo->nLocalScreen));

			DrawTmOsd(pScreenInfo, time(NULL));
			CREATE_EV(pScreenInfo->nOsdTask, 1, 0, m_pEnv->pEvBase, CDswlivevideo::cbOsdTask, pScreenInfo);
		}
		break;
	case DEV_MIXDVR_MIX:
	case DEV_MIXDVR_MIX_G:
		{
			int nWidth, nHeight;
			FT2DRectangle rect;
			nWidth = pScreenInfo->nScreen.width / 2;
			nHeight = pScreenInfo->nScreen.height / 3 * 2;
			rect.x = pLocalScreen[0].x = 0;
			rect.y = pLocalScreen[0].y = 0;
			rect.w = pLocalScreen[0].width = nWidth;
			rect.h = pLocalScreen[0].height = nHeight;
			DrawRect(pScreenInfo, &rect);
			nHeight /= 3;
			rect.x = pLocalScreen[1].x = nWidth;
			rect.y = pLocalScreen[1].y = 0;
			rect.w = pLocalScreen[1].width = nWidth;
			rect.h = pLocalScreen[1].height = nHeight;
			DrawRect(pScreenInfo, &rect);
			rect.x = pLocalScreen[2].x = nWidth;
			rect.y = pLocalScreen[2].y = nHeight;
			rect.w = pLocalScreen[2].width = nWidth;
			rect.h = pLocalScreen[2].height = nHeight;
			DrawRect(pScreenInfo, &rect);
			rect.x = pLocalScreen[3].x = nWidth;
			rect.y = pLocalScreen[3].y = nHeight * 2;
			rect.w = pLocalScreen[3].width = nWidth;
			rect.h = pLocalScreen[3].height = nHeight;
			DrawRect(pScreenInfo, &rect);

			nWidth = pScreenInfo->nScreen.width / 4;
			nHeight = pScreenInfo->nScreen.height / 3;
			rect.x = pRemoteScreen[0].x = 0;
			rect.y = pRemoteScreen[0].y = pLocalScreen[0].height;
			rect.w = pRemoteScreen[0].width = nWidth;
			rect.h = pRemoteScreen[0].height = nHeight;
			DrawRect(pScreenInfo, &rect);
			rect.x = pRemoteScreen[1].x = nWidth * 1;
			rect.y = pRemoteScreen[1].y = pLocalScreen[0].height;
			rect.w = pRemoteScreen[1].width = nWidth;
			rect.h = pRemoteScreen[1].height = nHeight;
			DrawRect(pScreenInfo, &rect);
			rect.x = pRemoteScreen[2].x = nWidth * 2;
			rect.y = pRemoteScreen[2].y = pLocalScreen[0].height;
			rect.w = pRemoteScreen[2].width = nWidth;
			rect.h = pRemoteScreen[2].height = nHeight;
			DrawRect(pScreenInfo, &rect);
			rect.x = pRemoteScreen[3].x = nWidth * 3;
			rect.y = pRemoteScreen[3].y = pLocalScreen[0].height;
			rect.w = pRemoteScreen[3].width = nWidth;
			rect.h = pRemoteScreen[3].height = nHeight;
			DrawRect(pScreenInfo, &rect);

			pScreenInfo->nLocalScreen[0] = pLocalScreen++;
			pScreenInfo->nLocalScreen[1] = pLocalScreen++;
			pScreenInfo->nLocalScreen[2] = pLocalScreen++;
			pScreenInfo->nLocalScreen[3] = pLocalScreen++;

			pScreenInfo->nRemoteScreen[0] = pRemoteScreen++;
			pScreenInfo->nRemoteScreen[1] = pRemoteScreen++;
			pScreenInfo->nRemoteScreen[2] = pRemoteScreen++;
			pScreenInfo->nRemoteScreen[3] = pRemoteScreen++;

			DrawTxtOsd(pScreenInfo);
			DrawTmOsd(pScreenInfo, time(NULL));
			CREATE_EV(pScreenInfo->nOsdTask, 1, 0, m_pEnv->pEvBase, CDswlivevideo::cbOsdTask, pScreenInfo);
		}
		break;
	default:
		LOG4CPLUS_WARN(log_dsw, "Invalid device type [" << m_pEnv->nDevType << "]!");
		driver_close_device(&m_nScreenInfo.gfx_device); 
		break;
	}

	DECLARE_ATTR(win_attr, gm_win_attr_t);
	DECLARE_ATTR(file_attr, gm_file_attr_t);
	DECLARE_ATTR(cap_attr, gm_cap_attr_t);
	int i;
	m_pClrwinBuf = new unsigned char[32 * 32 * 2 * sizeof(char)];
	for (i = 0; i < (32 * 32 / 2); i++)
		*(unsigned int *)(m_pClrwinBuf + 4 * i) = 0x10801080;
	pScreenInfo->groupfd = NULL;
	memset(pScreenInfo->bindfd_local, NULL, sizeof(pScreenInfo->bindfd_local));
	memset(pScreenInfo->bindfd_remote, NULL, sizeof(pScreenInfo->bindfd_remote));
	memset(pScreenInfo->cap_obj_local, NULL, sizeof(pScreenInfo->cap_obj_local));
	memset(pScreenInfo->file_obj_remote, NULL, sizeof(pScreenInfo->file_obj_remote));
	memset(pScreenInfo->win_obj_local, NULL, sizeof(pScreenInfo->win_obj_local));
	memset(pScreenInfo->win_obj_remote, NULL, sizeof(pScreenInfo->win_obj_remote));
	pScreenInfo->groupfd = gm_new_groupfd(); 

	if ((m_pEnv->nDevType == DEV_MIXDVR_DVR) || (m_pEnv->nDevType == DEV_MIXDVR_DVR_G)){
		for (i = 0; i < MAX_CHANNEL_LOCAL; i++){
			if (pScreenInfo->nLocalScreen[i]){
				pScreenInfo->cap_obj_local[i] = gm_new_obj(GM_CAP_OBJECT);
				pScreenInfo->win_obj_local[i] = gm_new_obj(GM_WIN_OBJECT);
				cap_attr.cap_vch = i;
				cap_attr.path = 0;
				cap_attr.enable_mv_data = 0;
				gm_set_attr(pScreenInfo->cap_obj_local[i], &cap_attr);
				Setup_win_attr(pScreenInfo->nLocalScreen[i], &win_attr, i, 1, 0, &pScreenInfo->nScreen);
				gm_set_attr(pScreenInfo->win_obj_local[i], &win_attr);

				pScreenInfo->bindfd_local[i] = gm_bind(pScreenInfo->groupfd, pScreenInfo->cap_obj_local[i], pScreenInfo->win_obj_local[i]);
			}
		}
	}
	else if ((m_pEnv->nDevType == DEV_MIXDVR_NVR) || (m_pEnv->nDevType == DEV_MIXDVR_NVR_G)){
		for (i = 0; i < MAX_CHANNEL_REMOTE; i++){
			if (pScreenInfo->nRemoteScreen[i]){
				pScreenInfo->file_obj_remote[i] = gm_new_obj(GM_FILE_OBJECT);
				pScreenInfo->win_obj_remote[i] = gm_new_obj(GM_WIN_OBJECT);
				file_attr.vch = i;
				file_attr.max_width = F_WIDTH;
				file_attr.max_height = F_HEIGHT;
				gm_set_attr(pScreenInfo->file_obj_remote[i], &file_attr);
				Setup_win_attr(pScreenInfo->nRemoteScreen[i], &win_attr, i, 1, 0, &pScreenInfo->nScreen);
				gm_set_attr(pScreenInfo->win_obj_remote[i], &win_attr);
				pScreenInfo->bindfd_remote[i] = gm_bind(pScreenInfo->groupfd, pScreenInfo->file_obj_remote[i], pScreenInfo->win_obj_remote[i]);
			}
		}
	}
	else  if ((m_pEnv->nDevType == DEV_MIXDVR_MIX) || (m_pEnv->nDevType == DEV_MIXDVR_MIX_G)){
		for (i = 0; i < MAX_CHANNEL_LOCAL; i++){
			if (pScreenInfo->nLocalScreen[i]){
				pScreenInfo->cap_obj_local[i] = gm_new_obj(GM_CAP_OBJECT);
				pScreenInfo->win_obj_local[i] = gm_new_obj(GM_WIN_OBJECT);
				cap_attr.cap_vch = i;
				cap_attr.path = 0;
				cap_attr.enable_mv_data = 0;
				gm_set_attr(pScreenInfo->cap_obj_local[i], &cap_attr);
				Setup_win_attr(pScreenInfo->nLocalScreen[i], &win_attr, i, 1, 0, &pScreenInfo->nScreen);
				gm_set_attr(pScreenInfo->win_obj_local[i], &win_attr);

				pScreenInfo->bindfd_local[i] = gm_bind(pScreenInfo->groupfd, pScreenInfo->cap_obj_local[i], pScreenInfo->win_obj_local[i]);
			}
		}
		for (i = 0; i < MAX_CHANNEL_REMOTE; i++){
			if (pScreenInfo->nRemoteScreen[i]){
				pScreenInfo->file_obj_remote[i] = gm_new_obj(GM_FILE_OBJECT);
				pScreenInfo->win_obj_remote[i] = gm_new_obj(GM_WIN_OBJECT);
				file_attr.vch = i;
				file_attr.max_width = F_WIDTH;
				file_attr.max_height = F_HEIGHT;
				gm_set_attr(pScreenInfo->file_obj_remote[i], &file_attr);
				Setup_win_attr(pScreenInfo->nRemoteScreen[i], &win_attr, i, 1, 0, &pScreenInfo->nScreen);
				gm_set_attr(pScreenInfo->win_obj_remote[i], &win_attr);
				pScreenInfo->bindfd_remote[i] = gm_bind(pScreenInfo->groupfd, pScreenInfo->file_obj_remote[i], pScreenInfo->win_obj_remote[i]);
			}
		}
	}
	if (gm_apply(pScreenInfo->groupfd) < 0)
		LOG4CPLUS_WARN(log_dsw, "Error! gm_apply fail, AP procedure something wrong!");
	else{
		if ((m_pEnv->nDevType == DEV_MIXDVR_DVR) || (m_pEnv->nDevType == DEV_MIXDVR_DVR_G)){
			for (i = 0; i < MAX_CHANNEL_LOCAL; i++){
				if (pScreenInfo->nLocalScreen[i]){
					ClearWin(pScreenInfo->nLocalScreen[i], 0, &pScreenInfo->nScreen);
				}
			}
		}
		else if ((m_pEnv->nDevType == DEV_MIXDVR_NVR) || (m_pEnv->nDevType == DEV_MIXDVR_NVR_G)){
			for (i = 0; i < MAX_CHANNEL_REMOTE; i++){
				if (pScreenInfo->nRemoteScreen[i]){
					ClearWin(pScreenInfo->nRemoteScreen[i], 0, &pScreenInfo->nScreen);
				}
			}
		}
		else  if ((m_pEnv->nDevType == DEV_MIXDVR_MIX) || (m_pEnv->nDevType == DEV_MIXDVR_MIX_G)){
			for (i = 0; i < MAX_CHANNEL_LOCAL; i++){
				if (pScreenInfo->nLocalScreen[i]){
					ClearWin(pScreenInfo->nLocalScreen[i], 0, &pScreenInfo->nScreen);
				}
			}
			for (i = 0; i < MAX_CHANNEL_REMOTE; i++){
				if (pScreenInfo->nRemoteScreen[i]){
					ClearWin(pScreenInfo->nRemoteScreen[i], 0, &pScreenInfo->nScreen);
				}
			}
		}
		
		pScreenInfo->pCaller = this;
		pthread_create(&m_nThreadID, NULL, CDswlivevideo::cbPlaybackThreadFunc, pScreenInfo);
	}
	m_nScreenInfo.bValid = true;

	gm_system_t nSystem;
	if (gm_get_sysinfo(&nSystem) == 0){
		if (nSystem.lcd[GM_LCD1].valid)
			gm_adjust_disp(GM_LCD1, 0, 0, nSystem.lcd[GM_LCD1].dim.width, nSystem.lcd[GM_LCD1].dim.height);
	}

	if ((m_pEnv->nDevType == DEV_MIXDVR_DVR) || (m_pEnv->nDevType == DEV_MIXDVR_MIX) ||
		(m_pEnv->nDevType == DEV_MIXDVR_DVR_G) || (m_pEnv->nDevType == DEV_MIXDVR_MIX_G)){
		gm_register_notify_handler(GM_NOTIFY_SIGNAL_LOSS, CDswlivevideo::cbLiveNotify);
		gm_register_notify_handler(GM_NOTIFY_SIGNAL_PRESENT, CDswlivevideo::cbLiveNotify);
	}
}

void CDswlivevideo::Setup_win_attr(gm_rect_t *pScreen, gm_win_attr_t *win_attr, int ch, int visible, int fullscreen, gm_dim_t *pSize)
{
	win_attr->lcd_vch = GM_LCD0;
	win_attr->rect.x = (fullscreen == 1) ? 0 : pScreen->x;
	win_attr->rect.y = (fullscreen == 1) ? 0 : pScreen->y;
	win_attr->rect.width = (fullscreen == 1) ? pSize->width : pScreen->width;
	win_attr->rect.height = (fullscreen == 1) ? pSize->height : pScreen->height;
	win_attr->visible = visible;
}

void CDswlivevideo::ClearWin(gm_rect_t *pScreen, int fullscreen, gm_dim_t *pSize)
{
	gm_clear_window_t cw_str;
	cw_str.in_w = 32;
	cw_str.in_h = 32;
	cw_str.in_fmt = GM_FMT_YUV422;
	cw_str.buf = m_pClrwinBuf;
	cw_str.out_x = (fullscreen == 1) ? 0 : pScreen->x;
	cw_str.out_y = (fullscreen == 1) ? 0 : pScreen->y;
	cw_str.out_w = (fullscreen == 1) ? pSize->width : pScreen->width;
	cw_str.out_h = (fullscreen == 1) ? pSize->height : pScreen->height;
	cw_str.mode = (gm_clear_window_mode_t)GM_ACTIVE_IMMEDIATELY;
	if (gm_clear_window(GM_LCD0, &cw_str) != 0)
		LOG4CPLUS_ERROR(log_dsw, "Clear window failed!");
}

void CDswlivevideo::UnInitLiveView(LPST_SCREEN_INFO_T pScreenInfo)
{
	if (m_nThreadID != INVALID_PTHREAD_ID)
		pthread_join(m_nThreadID, NULL);
	if (m_nScreenInfo.bValid){
		CLEAR_EV(pScreenInfo->nOsdTask);
		UnInitSignal(&pScreenInfo->nSignal);
		driver_close_device(&pScreenInfo->gfx_device);
		int i;
		bool bNeedApply = false;
		for (i = 0; i < MAX_CHANNEL_LOCAL; i++){
			if (pScreenInfo->bindfd_local[i]){
				gm_unbind(pScreenInfo->bindfd_local[i]);
				bNeedApply = true;
			}
		}
		if (bNeedApply)
			gm_apply(pScreenInfo->groupfd);
		for (i = 0; i < MAX_CHANNEL_LOCAL; i++){
			if (pScreenInfo->cap_obj_local[i])
				gm_delete_obj(pScreenInfo->cap_obj_local[i]);
			if (pScreenInfo->win_obj_local[i])
				gm_delete_obj(pScreenInfo->win_obj_local[i]);
		}
		bNeedApply = false;
		for (i = 0; i < MAX_CHANNEL_REMOTE; i++){
			if (pScreenInfo->bindfd_remote[i]){
				gm_unbind(pScreenInfo->bindfd_remote[i]);
				bNeedApply = true;
			}
		}
		if (bNeedApply)
			gm_apply(pScreenInfo->groupfd);
		for (i = 0; i < MAX_CHANNEL_REMOTE; i++){
			if (pScreenInfo->file_obj_remote[i])
				gm_delete_obj(pScreenInfo->file_obj_remote[i]);
			if (pScreenInfo->win_obj_remote[i])
				gm_delete_obj(pScreenInfo->win_obj_remote[i]);
		}
		gm_delete_groupfd(pScreenInfo->groupfd);
		if (m_pClrwinBuf)
			delete m_pClrwinBuf;
	}
}

void CDswlivevideo::PlaybackThreadFunc(LPST_SCREEN_INFO_T pScreenInfo)
{
	LOG4CPLUS_DEBUG(log_dsw, "Start live view thread!");
	unsigned long nVideoCoderHandle_remote;
	unsigned long *pVideoCoderHandle_remote;
	ST_VIDEO_FRAME_T nVideoFrame_remote[MAX_CHANNEL_REMOTE];
	char *pVBuffer_Remote[MAX_CHANNEL_REMOTE];
	int i, nVideoSeq_remote[MAX_CHANNEL_REMOTE];
	gm_dec_multi_bitstream_t multi_bs[MAX_CHANNEL_REMOTE];
	bool bHaveFrame, bNeedKeyFrame[MAX_CHANNEL_REMOTE];
	time_t nLiveTm[MAX_CHANNEL_REMOTE], nHasFrameTm[MAX_CHANNEL_REMOTE];
	int nPlaybackCount;

	unsigned long nBaseTV[MAX_CHANNEL_REMOTE] = {0};
	struct timeval nCurTm[MAX_CHANNEL_REMOTE];
	unsigned long nFrameDTS[MAX_CHANNEL_REMOTE] = {0};
	unsigned long nFrameBaseDTS[MAX_CHANNEL_REMOTE] = {0};
	int64_t nLastDTS = 0;
	int64_t nLastShowDTS = 0;
	
	memset(nLiveTm, 0, sizeof(nLiveTm));
	memset(nHasFrameTm, 0, sizeof(nHasFrameTm));
	nVideoCoderHandle_remote = 0;
	SendMessage(PMSG_GET_VIDEOCODEC_REMOTE_CLASS, (void*)&nVideoCoderHandle_remote);
	pVideoCoderHandle_remote = &nVideoCoderHandle_remote;
	if (*pVideoCoderHandle_remote == 0)
		goto END_LIVE;

	for (i = 0; i < MAX_CHANNEL_REMOTE; i++){
		pVBuffer_Remote[i] = new char[V_BITSTREAM_LEN];
		memset(&nVideoFrame_remote[i], 0, sizeof(ST_VIDEO_FRAME_T));
		nVideoFrame_remote[i].pFrame = (void*)pVBuffer_Remote[i];
		nVideoFrame_remote[i].length = 0;
		nVideoFrame_remote[i].ch_num = i;
		nVideoFrame_remote[i].sub_num = REC_REMOTE_STREAM;
		nVideoSeq_remote[i] = 0;
		bNeedKeyFrame[i] = true;
		nHasFrameTm[i] = time(NULL);
	}
	
	while(!m_pEnv->bExit){
		memset(multi_bs, 0, sizeof(multi_bs));
		bHaveFrame = false;
		nPlaybackCount = 0;

		for (i = 0; i < MAX_CHANNEL_REMOTE; i++){
			gettimeofday(&nCurTm[i], NULL);
			if (abs(nLiveTm[i] - time(NULL) ) > EXTCAM_OFFLINE_TIMEOUT){
				SetVideoSignal(i, false, VIDEO_NO_SIGNAL);
				nLiveTm[i] = time(NULL);
				nVideoSeq_remote[i] = 0;
				nBaseTV[i] = 0;
			}
			if (nVideoFrame_remote[i].length <= 0){
				nVideoFrame_remote[i].seq = nVideoSeq_remote[i];
				nVideoFrame_remote[i].length = V_BITSTREAM_LEN;
				nVideoFrame_remote[i].pFrame = (void*)pVBuffer_Remote[i];
				if (((CDswbase*)(*pVideoCoderHandle_remote))->HandleMessage(PMSG_GET_VIDEOFRAME, (void*)&nVideoFrame_remote[i]) == 0){
					nVideoFrame_remote[i].length = 0;
					continue;
				}
			}
			if (((nVideoSeq_remote[i] == 0) && !nVideoFrame_remote[i].is_keyframe) || (bNeedKeyFrame[i] && !nVideoFrame_remote[i].is_keyframe)){
				nVideoSeq_remote[i] = nVideoFrame_remote[i].seq + 1;
				nBaseTV[i] = 0;
				nVideoFrame_remote[i].length = 0;
				continue;
			}
#if 1
			if (((nVideoFrame_remote[i].seq >= (nVideoSeq_remote[i] + 1)) && !bNeedKeyFrame[i]) ||
				(abs(nHasFrameTm[i] - time(NULL)) > 5)){
				bNeedKeyFrame[i] = true;
				printf("ch = %d, seq = %d, %d, %d\n", i, nVideoFrame_remote[i].seq, nVideoSeq_remote[i] + 1,
					abs(nHasFrameTm[i] - time(NULL)));
				nVideoSeq_remote[i] = nVideoFrame_remote[i].seq + 1;
				nBaseTV[i] = 0;
				nVideoFrame_remote[i].length = 0;
				nHasFrameTm[i] = time(NULL);
				continue;
			}
#endif
			if (abs(nLiveTm[i] - time(NULL) ) > 5){
				SetVideoSignal(i, false, VIDEO_PRESENT);
				nLiveTm[i] = time(NULL);
			}
			if (nBaseTV[i] != 0){
				nFrameDTS[i] = nVideoFrame_remote[i].nDTS / 90 - nFrameBaseDTS[i] + nBaseTV[i];
				if (nFrameDTS[i] > (nCurTm[i].tv_sec * 1000 + nCurTm[i].tv_usec / 1000))
					continue;
/*
				if (memcmp(pVBuffer_Remote[i], "\x00\x00\x00\x01", 4) != 0){
					printf("ch = %d, data = %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x\n",
						i, pVBuffer_Remote[i][0], pVBuffer_Remote[i][1], pVBuffer_Remote[i][2], pVBuffer_Remote[i][3],
						pVBuffer_Remote[i][4], pVBuffer_Remote[i][5], pVBuffer_Remote[i][6], pVBuffer_Remote[i][7],
						pVBuffer_Remote[i][8], pVBuffer_Remote[i][9]);
				}
				if (i == 0){
					printf("jiffer = %d, %d, %lld\n", (nCurTm[i].tv_sec * 1000 + nCurTm[i].tv_usec / 1000) - nFrameDTS[i],
						(nVideoFrame_remote[i].nDTS - nLastDTS) / 90,
						(nCurTm[i].tv_sec * 1000 + nCurTm[i].tv_usec / 1000) - nLastShowDTS);
					nLastDTS = nVideoFrame_remote[i].nDTS;
					nLastShowDTS = (nCurTm[i].tv_sec * 1000 + nCurTm[i].tv_usec / 1000);
				}
*/
			}
			else if (nBaseTV[i] == 0){
				nBaseTV[i] = nCurTm[i].tv_sec * 1000 + nCurTm[i].tv_usec / 1000;// + nVideoFrame_remote[i].nDTS / 90;
				nFrameBaseDTS[i] = nVideoFrame_remote[i].nDTS / 90;
			}

			bNeedKeyFrame[i] = false;
			multi_bs[nPlaybackCount].bindfd = pScreenInfo->bindfd_remote[i];
			multi_bs[nPlaybackCount].bs_buf = pVBuffer_Remote[i];
			multi_bs[nPlaybackCount].bs_buf_len = nVideoFrame_remote[i].length;
			nPlaybackCount++;
			bHaveFrame = true;
			nHasFrameTm[i] = time(NULL);
			if (nVideoSeq_remote[i] != nVideoFrame_remote[i].seq)
				printf("ss =%d, %d, %d\n", i, nVideoSeq_remote[i], nVideoFrame_remote[i].seq);
			nVideoSeq_remote[i] = nVideoFrame_remote[i].seq + 1;
			nVideoFrame_remote[i].length = 0;
		}
		if (bHaveFrame){
			int ret;
			if ((ret = gm_send_multi_bitstreams(multi_bs, nPlaybackCount, 100)) < 0){
				LOG4CPLUS_DEBUG(log_dsw, "Send bitstream error! ret = " << ret);
			}
		}
		else
			usleep(100 * 1);
//		if (bHaveFrame)
//			PlaybackDelay(MAKEINTERVALTIME_US(nStartTm, nEndTm), 25);
	}
	for (i = 0; i < MAX_CHANNEL_REMOTE; i++)
		delete pVBuffer_Remote[i];
END_LIVE:
	LOG4CPLUS_DEBUG(log_dsw, "Exit live view thread!");
}

void CDswlivevideo::PlaybackDelay(unsigned int nInterval, int nFps)
{
	int nDuration;
	nDuration = (1000 * 1000) / nFps;
	if (nInterval >= nDuration)
		return;
	struct timeval tv;
	tv.tv_sec = (nDuration - nInterval) / 1000000;
	tv.tv_usec = (nDuration - nInterval) % 1000000;
	select(0, NULL, NULL, NULL, &tv);
}

void CDswlivevideo::DrawRect(LPST_SCREEN_INFO_T pScreenInfo, FT2DRectangle* pRect)
{
	int i = LINE_WIDTH;
	pScreenInfo->gfx_device.accel_do = FT2D_DRAWRECT; 
	pScreenInfo->gfx_device.accel_param = (FT2D_SettingFlags_T)(FT2D_COLOR_SET | FT2D_DSTINATION_SET);
	do{
		pScreenInfo->accel_data->color = COLOUR8888(0xff, 0xff, 0xff, 0);
		if (pScreenInfo->gfx_funcs->CheckState(&pScreenInfo->gfx_device) < 0 || pScreenInfo->gfx_funcs->SetState(&pScreenInfo->gfx_device) < 0){
			LOG4CPLUS_ERROR(log_dsw, "Setstate or Check state fail!");
		}
		else{
			pScreenInfo->gfx_funcs->DrawRectangle(&pScreenInfo->gfx_device , pRect);
			pRect->x++;
			pRect->y++;
			pRect->w -= 2;
			pRect->h -= 2;
		}
	}while(i-- > 0);
	pScreenInfo->gfx_funcs->EmitCommands(&pScreenInfo->gfx_device);
}

int CDswlivevideo::ConvertChar2WChar(char* pIn, wchar_t* pOut)
{
	char* pPos = pIn;
	wchar_t* pOutPos = pOut;
	int nLen = strlen(pIn);
	int ncount = 0;

	while(nLen > 0){
		memset(pOutPos, 0, sizeof(wchar_t));
		if (*pPos & 0x80){
			((char*)pOutPos)[0] = pPos[1];
			((char*)pOutPos)[1] = pPos[0];
			pPos += 2;
			nLen--;
		}
		else{
			((char*)pOutPos)[0] = pPos[0];
			pPos++;
		}
		nLen--;
		ncount++;
		pOutPos++;
	}
	return ncount;
}

int CDswlivevideo::LoadFont(FILE* fp, wchar_t* pText, int ncount, unsigned char* pDot)
{
	int offset, i, nret;
	nret = 0;
	for (i = 0; i < ncount; i++){
		unsigned char* pPos = (unsigned char*)pText;
		unsigned char tmp = pPos[0];
		pPos[0] = pPos[1];
		pPos[1] = tmp;
		if (pPos[0] & 0x80)
			offset = (94 * (unsigned int)(pPos[0] - 0xa0 - 1) + (pPos[1] - 0xa0 - 1)) * 32;
		else
			offset = (94 * (unsigned int)(3 - 1) + (pPos[1] - 0x20 - 1)) * 32;
		fseek(fp, offset, SEEK_SET);
		fread(pDot, 1, 32, fp);
		pText++;
		pDot += 32;
		nret += 32;
	}
	return nret;
}

void CDswlivevideo::ConvertDot2Bmp565(unsigned char* pDot, int nlen, unsigned char* pBmp)
{
	unsigned char key[8] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
	int i, j, k, flag;
	while(nlen > 0){
		for(k = 0; k < 16; k++){
			for(j = 0; j < 2; j++){
				for(i = 0; i < 8; i++){
					flag = pDot[k * 2 + j] & key[i];
					if (flag){
						*((unsigned short*)pBmp) = RGB24_2_565(255, 255, 255);
//						printf("*");
					}
					else{
						*((unsigned short*)pBmp) = RGB24_2_565(0, 0, 0);
//						printf(" ");
					}
					pBmp += 2;
				}
			}
//			printf("\n");
		}
//		printf("\n");
		nlen -= 32;
		pDot += 32;
	}
}

void CDswlivevideo::MakeOsdFont(LPST_SCREEN_INFO_T pScreenInfo, LPST_VIDEO_PARAM pVParam)
{
	int i, ncount;
	wchar_t nosd_text[MAX_OSDFONT];
	unsigned char nDot[MAX_OSDFONT * 32];
	FILE * fp = NULL;
	if((fp = fopen(OSD_ZK, "rb")) == NULL){
		LOG4CPLUS_ERROR(log_dsw, "Open " << OSD_ZK << " failed!");
		return;
	}
	for (i = 0; i < MAX_CHANNEL_LOCAL; i++){
		pScreenInfo->nFontCount[i] = ConvertChar2WChar(pVParam->nVParam[i].nOsd.sosd, nosd_text);
		ncount = LoadFont(fp, nosd_text, pScreenInfo->nFontCount[i], nDot);
		ConvertDot2Bmp565(nDot, ncount, pScreenInfo->nFontBmp[i]);
	}
	char sDigital[13] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', ' ', ':'};
	ncount = (int)mbstowcs(nosd_text, sDigital, 13);
	ncount = LoadFont(fp, nosd_text, ncount, nDot);
	ConvertDot2Bmp565(nDot, ncount, pScreenInfo->nDigitalFontBmp);

	fclose(fp);
}

unsigned int CDswlivevideo::think2d_modesize(unsigned int mode)
{
	switch (mode)
	{
		case FT2D_RGB_5650:
		case FT2D_RGBA_5551:
		case FT2D_RGBA4444:
		case FT2D_ARGB_1555:
			return 2;

		case FT2D_RGB_888:
		case FT2D_ARGB_8888:
		case FT2D_RGBA_8888:
			return 4;
		default : 
		    return 0;	
	}
	return 0;
}

void CDswlivevideo::DrawTxtOsd(LPST_SCREEN_INFO_T pScreenInfo)
{
	unsigned char* pBuffer = (unsigned char*)pScreenInfo->tar_data->surface_vaddr;
	int nCh, nOsdWidth, nOsdHeight, nCount, nFontIndex;
	unsigned char *pDestPos, *pSrcPos;
	for (nCh = 0; nCh < MAX_CHANNEL_LOCAL; nCh++){
		for (nFontIndex = 0; nFontIndex < pScreenInfo->nFontCount[nCh]; nFontIndex++){
			pDestPos = pBuffer + 
				(pScreenInfo->nLocalScreen[nCh]->y + TXT_OSD_OFFSET_Y) * pScreenInfo->tar_data->width * think2d_modesize(pScreenInfo->tar_data->bpp) +
				(pScreenInfo->nLocalScreen[nCh]->x + TXT_OSD_OFFSET_X) * think2d_modesize(pScreenInfo->tar_data->bpp) +
				nFontIndex * 16 * think2d_modesize(pScreenInfo->tar_data->bpp);
			nOsdWidth = 16 * think2d_modesize(pScreenInfo->tar_data->bpp);
			nOsdHeight = 16;
			pSrcPos = pScreenInfo->nFontBmp[nCh] + nFontIndex * 16 * 16 * think2d_modesize(pScreenInfo->tar_data->bpp);
			nCount = 0;
			while(nOsdHeight-- > 0){
				memcpy(pDestPos, pSrcPos, nOsdWidth);
				pSrcPos += nOsdWidth;
				pDestPos = (nCount * pScreenInfo->tar_data->width * think2d_modesize(pScreenInfo->tar_data->bpp)) + (pBuffer + 
					(pScreenInfo->nLocalScreen[nCh]->y + TXT_OSD_OFFSET_Y) * pScreenInfo->tar_data->width * think2d_modesize(pScreenInfo->tar_data->bpp)) +
					(pScreenInfo->nLocalScreen[nCh]->x + TXT_OSD_OFFSET_X) * think2d_modesize(pScreenInfo->tar_data->bpp) + 
					nFontIndex * 16 * think2d_modesize(pScreenInfo->tar_data->bpp);
				nCount++;
			}
		}
	}
}

bool CDswlivevideo::DrawTmOsd(LPST_SCREEN_INFO_T pScreenInfo, time_t nNow)
{
	if (pScreenInfo->nLastTm == nNow)
		return false;
	if ((m_pEnv->nDevType != DEV_MIXDVR_NVR) && (m_pEnv->nDevType != DEV_MIXDVR_NVR_G)){
		char sNow[32], sLastTm[32];
		int nFontIndex, nCh, nOsdWidth, nOsdHeight, nCount;
		unsigned char *pDestPos, *pSrcPos;
		unsigned char* pBuffer = (unsigned char*)pScreenInfo->tar_data->surface_vaddr;
		strftime(sNow, sizeof(sNow), "%Y-%m-%d %H:%M:%S", localtime(&nNow));
		if (pScreenInfo->nLastTm == 0)
			memset(sLastTm, '+', sizeof(sLastTm));
		else
			strftime(sLastTm, sizeof(sLastTm), "%Y-%m-%d %H:%M:%S", localtime(&pScreenInfo->nLastTm));
		for (nFontIndex = 0; nFontIndex < strlen(sNow); nFontIndex++){
			if (sNow[nFontIndex] == sLastTm[nFontIndex])
				continue;
			for (nCh = 0; nCh < MAX_CHANNEL_LOCAL; nCh++){
				pDestPos = pBuffer + 
					(pScreenInfo->nLocalScreen[nCh]->y + pScreenInfo->nLocalScreen[nCh]->height + TM_OSD_OFFSET_Y) * pScreenInfo->tar_data->width * think2d_modesize(pScreenInfo->tar_data->bpp) +
					(pScreenInfo->nLocalScreen[nCh]->x + TM_OSD_OFFSET_X) * think2d_modesize(pScreenInfo->tar_data->bpp) +
					nFontIndex * 16 * think2d_modesize(pScreenInfo->tar_data->bpp);
				nOsdWidth = 16 * think2d_modesize(pScreenInfo->tar_data->bpp);
				nOsdHeight = 16;
				if (sNow[nFontIndex] == '-')
					pSrcPos = &pScreenInfo->nDigitalFontBmp[10 * 16 * 16 * 2];
				else if (sNow[nFontIndex] == ' ')
					pSrcPos = &pScreenInfo->nDigitalFontBmp[11 * 16 * 16 * 2];
				else if (sNow[nFontIndex] == ':')
					pSrcPos = &pScreenInfo->nDigitalFontBmp[12 * 16 * 16 * 2];
				else
					pSrcPos = &pScreenInfo->nDigitalFontBmp[(sNow[nFontIndex] - 0x30) * 16 * 16 * 2];
				nCount = 0;
				while(nOsdHeight-- > 0){
					memcpy(pDestPos, pSrcPos, nOsdWidth);
					pSrcPos += nOsdWidth;
					pDestPos = (nCount * pScreenInfo->tar_data->width * think2d_modesize(pScreenInfo->tar_data->bpp)) + (pBuffer + 
						(pScreenInfo->nLocalScreen[nCh]->y + pScreenInfo->nLocalScreen[nCh]->height + TM_OSD_OFFSET_Y) * pScreenInfo->tar_data->width * think2d_modesize(pScreenInfo->tar_data->bpp)) +
						(pScreenInfo->nLocalScreen[nCh]->x + TM_OSD_OFFSET_X) * think2d_modesize(pScreenInfo->tar_data->bpp) +
						nFontIndex * 16 * think2d_modesize(pScreenInfo->tar_data->bpp);
					nCount++;
				}
			}
		}
	}
	pScreenInfo->nLastTm = nNow;
	return true;
}

void CDswlivevideo::OsdTask(int fd, short events, LPST_SCREEN_INFO_T pScreenInfo)
{
	if (DrawTmOsd(pScreenInfo, time(NULL)))
		DrawVideoSignal(&pScreenInfo->nSignal, pScreenInfo);
	TRIG_EV(pScreenInfo->nOsdTask, 0, 250 * 1000);
}

void CDswlivevideo::cbLiveNotify(gm_obj_type_t obj_type, int vch, gm_notify_t notify)
{
	if (notify == GM_NOTIFY_SIGNAL_LOSS){
		LOG4CPLUS_DEBUG(log_dsw, "CH [ " << vch <<  " ] Signal Loss!");
		g_pLiveVideo->SetVideoSignal(vch, true, VIDEO_NO_SIGNAL);
	}
	else if (notify == GM_NOTIFY_SIGNAL_PRESENT){
		LOG4CPLUS_DEBUG(log_dsw, "CH [ " << vch <<  " ] Signal Present!!");
		g_pLiveVideo->SetVideoSignal(vch, true, VIDEO_PRESENT);
	}
}

void CDswlivevideo::SetVideoSignal(int nCh, bool bLocal, EN_VIDEO_SIGNAL nType)
{
	MUTEX_LOCK(&m_nScreenInfo.nSignal.nLock);
	if (bLocal){
		m_nScreenInfo.nSignal.nMask |= 1 << nCh;
		m_nScreenInfo.nSignal.nSignal_local[nCh] = nType;
	}
	else{
		m_nScreenInfo.nSignal.nMask |= 1 << (nCh + MAX_CHANNEL_LOCAL);
		m_nScreenInfo.nSignal.nSignal_remote[nCh] = nType;
	}
	MUTEX_UNLOCK(&m_nScreenInfo.nSignal.nLock);
}

void CDswlivevideo::DrawVideoSignal(LPST_SIGNAL_T pSignal, LPST_SCREEN_INFO_T pScreenInfo)
{
	ST_SIGNAL_T nSignal;
	MUTEX_LOCK(&pSignal->nLock);
	if (pSignal->nMask){
		memcpy(&nSignal, pSignal, sizeof(nSignal));
		pSignal->nMask = 0;
	}
	else
		nSignal.nMask = 0;
	MUTEX_UNLOCK(&pSignal->nLock);
	if (nSignal.nMask == 0)
		return;
	if ((nSignal.nMask & MASK_SIGNAL_LOCAL_0) && pScreenInfo->nLocalScreen[0])
		DrawPic(nSignal.nSignal_local[0] == VIDEO_NO_SIGNAL, pScreenInfo->nLocalScreen[0], pScreenInfo);
	if ((nSignal.nMask & MASK_SIGNAL_LOCAL_1) && pScreenInfo->nLocalScreen[1])
		DrawPic(nSignal.nSignal_local[1] == VIDEO_NO_SIGNAL, pScreenInfo->nLocalScreen[1], pScreenInfo);
	if ((nSignal.nMask & MASK_SIGNAL_LOCAL_2) && pScreenInfo->nLocalScreen[2])
		DrawPic(nSignal.nSignal_local[2] == VIDEO_NO_SIGNAL, pScreenInfo->nLocalScreen[2], pScreenInfo);
	if ((nSignal.nMask & MASK_SIGNAL_LOCAL_3) && pScreenInfo->nLocalScreen[3])
		DrawPic(nSignal.nSignal_local[3] == VIDEO_NO_SIGNAL, pScreenInfo->nLocalScreen[3], pScreenInfo);
	if ((nSignal.nMask & MASK_SIGNAL_REMOTE_0) && pScreenInfo->nRemoteScreen[0])
		DrawPic(nSignal.nSignal_remote[0] == VIDEO_NO_SIGNAL, pScreenInfo->nRemoteScreen[0], pScreenInfo);
	if ((nSignal.nMask & MASK_SIGNAL_REMOTE_1) && pScreenInfo->nRemoteScreen[1])
		DrawPic(nSignal.nSignal_remote[1] == VIDEO_NO_SIGNAL, pScreenInfo->nRemoteScreen[1], pScreenInfo);
	if ((nSignal.nMask & MASK_SIGNAL_REMOTE_2) && pScreenInfo->nRemoteScreen[2])
		DrawPic(nSignal.nSignal_remote[2] == VIDEO_NO_SIGNAL, pScreenInfo->nRemoteScreen[2], pScreenInfo);
	if ((nSignal.nMask & MASK_SIGNAL_REMOTE_3) && pScreenInfo->nRemoteScreen[3])
		DrawPic(nSignal.nSignal_remote[3] == VIDEO_NO_SIGNAL, pScreenInfo->nRemoteScreen[3], pScreenInfo);

	SendMessage(PMSG_SET_SIGNALCHANGE, &nSignal);
}

void CDswlivevideo::DrawPic(bool bDraw, gm_rect_t* pScreen, LPST_SCREEN_INFO_T pScreenInfo)
{
	int nHeight = SIGNAL_HEIGHT;
	unsigned char* pBuffer = (unsigned char*)pScreenInfo->tar_data->surface_vaddr;
	int x = pScreen->x + (pScreen->width - SIGNAL_WIDTH) / 2;
	int y = pScreen->y + (pScreen->height - SIGNAL_HEIGHT) / 2;
	unsigned char* pDestPos = pBuffer + 
		y * pScreenInfo->tar_data->width * think2d_modesize(pScreenInfo->tar_data->bpp) +
		x * think2d_modesize(pScreenInfo->tar_data->bpp);
	unsigned char* pSrcPos = (unsigned char*)header_data;
	int nCount = 0;
	while(nHeight-- > 0){
		int nWidth;
		for (nWidth = 0; nWidth < SIGNAL_WIDTH; nWidth++){
			unsigned char nRgb[3] = {0};
			if (bDraw)
				HEADER_PIXEL(pSrcPos, nRgb);
			*((unsigned short*)(pDestPos + nWidth * 2)) = RGB24_2_565(nRgb[2], nRgb[1], nRgb[0]);
		}
		pDestPos = (nCount * pScreenInfo->tar_data->width * think2d_modesize(pScreenInfo->tar_data->bpp)) +
			(pBuffer + y * pScreenInfo->tar_data->width * think2d_modesize(pScreenInfo->tar_data->bpp)) +
			x * think2d_modesize(pScreenInfo->tar_data->bpp);
		nCount++;
	}
}

